package gykd.occ.occba.report.bazk_fpbs_rpt.newRpt;

import gykd.occ.occba.report.bazk_fpbs_rpt.FPBSConstants;
import gykd.utils.ArrayListHelper;
import gykd.utils.DateHelper;
import gykd.utils.ReportHelper;
import kd.bos.algo.*;
import kd.bos.algo.input.CollectionInput;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.report.*;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

public class FPBSDataRpt extends AbstractReportListDataPlugin {

    public static final BigDecimal ZERO = new BigDecimal(0);

    private String algoKey = this.getClass().getName();

    private Map<String, BigDecimal> saveDFData;


    private static String[] commonFields = {
            FPBSConstants.ORA_NUMBER_SQL,//资金池编码
            FPBSConstants.ORA_ORG,//结算组织
            FPBSConstants.ORA_CUS_NAME,//客户名称
            FPBSConstants.ORA_CUS_NUMBER,//客户编码
            FPBSConstants.ORA_CUS_PAYTYPE//付款方式
    };

    private static DataType[] commonDataTypes = {
            DataType.StringType,
            DataType.StringType,
            DataType.StringType,
            DataType.StringType,
            DataType.StringType,
    };

    private static String[] flowFields = {
            FPBSConstants.DATE_FIRST,//期初
            FPBSConstants.DATE_GET,//本期收款
            FPBSConstants.DATE_ADJUST,//本期调整
            FPBSConstants.DATE_ORDER,//本期要货
            FPBSConstants.DATE_RETURN,//本期退货
            FPBSConstants.DATE_END,//期末
            FPBSConstants.FPBS_END_AMT,//资金池期末
            FPBSConstants.LAST_DAY_AMT,//最后一天要货订单
            FPBSConstants.CHANNEL_NUM_DATE_FIRST,//渠道编码
            FPBSConstants.FLOW_ORG,
            FPBSConstants.TRIPARTITE_DIFFERENCES,//三方差异
            FPBSConstants.CHANNEL_NAME,//渠道名称
            FPBSConstants.CHANNEL_PAYTYPE,//渠道支付方式
            FPBSConstants.REC_CHANNEL//收款渠道
    };

    private static DataType[] flowDataTypes = {
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.BigDecimalType,
            DataType.StringType,
            DataType.StringType,
            DataType.BigDecimalType,
            DataType.StringType,
            DataType.StringType,
            DataType.StringType,
    };


    private QFilter getORAFilter(ReportQueryParam reportQueryParam) {
        QFilter all = new QFilter(FPBSConstants.FTL_FIRST_KEY, QCP.equals, FPBSConstants.FTL_FIRST_VAL);
        FilterInfo filterInfo = reportQueryParam.getFilter();
        //客户
        FilterItemInfo cusFilterItem = filterInfo.getFilterItem("bazk_cusftl");
        DynamicObjectCollection cuss = (DynamicObjectCollection) cusFilterItem.getValue();
        if (cuss != null && cuss.size() != 0) {
            List<Long> ids = cuss.stream().map(v -> (Long) v.get("id")).collect(Collectors.toList());
            all.and("customer.id", QCP.in, ids);
        }
        //结算组织
        FilterItemInfo orgFilterItem = filterInfo.getFilterItem("bazk_orgftl");
        DynamicObjectCollection orgs = (DynamicObjectCollection) orgFilterItem.getValue();
        if (orgs != null && orgs.size() != 0) {
            List<Long> ids = orgs.stream().map(v -> (Long) v.get("id")).collect(Collectors.toList());
            all.and("org.id", QCP.in, ids);
        }
        //渠道
        FilterItemInfo chaFilterItem = filterInfo.getFilterItem("bazk_chaftl");
        DynamicObjectCollection chas = (DynamicObjectCollection) chaFilterItem.getValue();
        if (chas != null && chas.size() != 0) {
            List<Long> ids = chas.stream().map(v -> (Long) v.get("id")).collect(Collectors.toList());
            all.and("channel", QCP.in, ids);
        }
        //查资金池类型为 品牌商的
//        all.and("type", QCP.equals, "A");
//        all.and("bazk_billstatusfield",QCP.not_equals,"1");
        return all;
    }

    //期初filter
    private QFilter getQCFilter(ReportQueryParam reportQueryParam, List<String> channelNums) throws ParseException {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        QFilter filter = new QFilter("1", QCP.equals, 1);
        //渠道过滤
        if (channelNums != null && channelNums.size() != 0) {
            filter.and("channel.number", QCP.in, channelNums);
        }

        //渠道
        FilterItemInfo chaFilterItem = filterInfo.getFilterItem("bazk_chaftl");
        DynamicObjectCollection chas = (DynamicObjectCollection) chaFilterItem.getValue();
        if (chas != null && chas.size() != 0) {
            List<Long> ids = chas.stream().map(v -> (Long) v.get("id")).collect(Collectors.toList());
            filter.and("channel.id", QCP.in, ids);
        }

        filter.and("transaction", QCP.not_equals, "B");
        //filter.and("bazk_bizdate", QCP.is_notnull, null);
        //结束日期
        FilterItemInfo endDateItem = filterInfo.getFilterItem("enddate");
        Date endDateFtl = (Date) endDateItem.getValue();
        if (endDateFtl != null) {
            Date monthLastDay = DateHelper.getMonthLastDay(endDateFtl);
            Date endDate = DateHelper.getDayLast(monthLastDay);
            QFilter tmp = new QFilter("bazk_bizdate", QCP.less_equals, DateHelper.getDayLast(endDate));
            tmp.or("createtime", QCP.is_notnull, null);
            filter.and(tmp);
        }
        //开始日期
//        FilterItemInfo beginDateItem = filterInfo.getFilterItem("begindate");
//        Date beginDateFtl = (Date) beginDateItem.getValue();
//        if (beginDateFtl != null) {
//            //获得开始日期前三个月的年月信息
//            Date threeAgo = DateHelper.getDateThreeMonAgoFromDate(beginDateFtl);
//            QFilter yyy = new QFilter("bazk_bizdate", QCP.large_equals, threeAgo);
//            filter.and(yyy);
//        }


        //结算组织
        FilterItemInfo orgFilterItem = filterInfo.getFilterItem("bazk_orgftl");
        DynamicObjectCollection orgs = (DynamicObjectCollection) orgFilterItem.getValue();
        if (orgs != null && orgs.size() != 0) {
            List<Long> ids = orgs.stream().map(v -> (Long) v.get("id")).collect(Collectors.toList());
            filter.and("org.id", QCP.in, ids);
        }


        //filter.and("channel.number",QCP.is_notnull,null);


        return filter;
    }

    private String getORASelect() {
        StringBuilder sb = new StringBuilder();
        sb.append(FPBSConstants.ORA_ID);//id
        sb.append(FPBSConstants.DH);//逗号
        sb.append(FPBSConstants.ORA_NUMBER_SQL);//资金池余额编码
        sb.append(FPBSConstants.DH);//逗号
        sb.append(FPBSConstants.ORA_ORG_SQL + FPBSConstants.AS + FPBSConstants.ORA_ORG);//结算组织
        sb.append(FPBSConstants.DH);//逗号
        sb.append(FPBSConstants.ORA_CUS_NUMBER_SQL + FPBSConstants.AS + FPBSConstants.ORA_CUS_NUMBER);//客户编码
        sb.append(FPBSConstants.DH);//逗号
        sb.append(FPBSConstants.ORA_CUS_NAME_SQL + FPBSConstants.AS + FPBSConstants.ORA_CUS_NAME);//客户名称
        sb.append(FPBSConstants.DH);//逗号
        sb.append(FPBSConstants.ORA_CUS_PAYTYPE_SQL + FPBSConstants.AS + FPBSConstants.ORA_CUS_PAYTYPE);//客户支付方式
        sb.append(FPBSConstants.DH);//逗号
        sb.append("channel.number" + FPBSConstants.AS + FPBSConstants.CHANNEL_NUM);//渠道编码
        sb.append(FPBSConstants.DH);
        sb.append("receivechannel.name " + FPBSConstants.AS + FPBSConstants.REC_CHANNEL);//收款渠道
        return sb.toString();
    }


    /**
     * 处理期初的DS
     *
     * @param QCdS
     * @return
     */
    private DataSet createDs(DataSet QCdS, ReportQueryParam reportQueryParam) throws ParseException {
        Collection<Object[]> coll = new ArrayList<>();//创建显示行字段
        //下面初始创建一个空的报表数据行
        RowMeta createRowMeta = RowMetaFactory.createRowMeta(flowFields, flowDataTypes);
        CollectionInput collectionInput = new CollectionInput(createRowMeta, coll);
        DataSet createDataSet = Algo.create(this.getClass().getName()).createDataSet(collectionInput);
        String preChannelNum = null;
        String preOrgName = null;
        String preRecCha = null;
        //第一行就是这个tempData
        Object[] tempData = new Object[flowFields.length];
        coll.add(tempData);
        String tempChannelNum = null;
        String tempOrgName = null;
        String tempRecCha = null;
        BigDecimal dateFirstTemp = ZERO;//期初
        BigDecimal dateNowGetTemp = ZERO;//本期收款
        BigDecimal dateNowAdjustTemp = ZERO;//本期调整
        BigDecimal dateNowOrderTemp = ZERO;//本期要货
        BigDecimal dateNowReturnTemp = ZERO;//本期退货
        BigDecimal dateEndTemp = ZERO;//期末

        BigDecimal threeDeference = ZERO;

        Date fpbsEndDate = DateHelper.getLongAgo();//资金池余额日期记录
        Date lastDayOrderDate = DateHelper.getLongAgo();//最后一天要货订单变动金额
        BigDecimal fpbsEndAmt = ZERO;//资金池期末余额
        BigDecimal lastDayOrderAmt = ZERO;//最后一天要货订单变动金额

        try {
            int flag = 0;
            for (Row row : QCdS) {
                if (flag == 0) {
                    preChannelNum = row.getString(FPBSConstants.CHANNEL_NUM);
                    preOrgName = row.getString(FPBSConstants.FLOW_ORG);
                    preRecCha = row.getString(FPBSConstants.REC_CHANNEL);
                    flag = 1;
                }
                System.out.println("行开始");
                tempChannelNum = row.getString(FPBSConstants.CHANNEL_NUM);
                tempOrgName = row.getString(FPBSConstants.FLOW_ORG);
                tempRecCha = row.getString(FPBSConstants.REC_CHANNEL);
                //这里比较巧妙，这里控制一个渠道的 要货 收款 退货 调整 数据共同使用一个coll,即一行
                if (!StringUtils.equals(preChannelNum, tempChannelNum) || !StringUtils.equals(preOrgName, tempOrgName) || !StringUtils.equals(preRecCha, tempRecCha)) {
                    //在切换渠道的时候 把前面总和出来的期初 写入刚刚的一行
                    dateFirstTemp = dateFirstTemp.subtract(threeDeference);
                    //查封存期初，获取期初值直接加上来
//                    String mapKey = preOrgName + "-" + preChannelNum + "-" + preRecCha;
//                    BigDecimal saveDF = saveDFData.get(mapKey);
//                    if (saveDF == null) {
//                        saveDF = ZERO;
//                    }
                    //dateFirstTemp = dateFirstTemp.add(saveDF);
                    tempData[0] = dateFirstTemp;
                    tempData[1] = dateNowGetTemp;
                    tempData[2] = dateNowAdjustTemp;
                    tempData[3] = dateNowOrderTemp;
                    tempData[4] = dateNowReturnTemp;
                    tempData[5] = dateEndTemp.add(dateFirstTemp).add(dateNowGetTemp).add(dateNowAdjustTemp).add(dateNowOrderTemp).add(dateNowReturnTemp);
                    //tempData[5] = dateEndTemp.add(dateFirstTemp).add(dateNowGetTemp).add(dateNowAdjustTemp).add(dateNowOrderTemp).add(dateNowReturnTemp);
                    tempData[6] = fpbsEndAmt;
                    tempData[7] = lastDayOrderAmt;
                    tempData[10] = threeDeference;

                    //清理期初temp
                    dateFirstTemp = ZERO;
                    dateNowGetTemp = ZERO;
                    dateNowAdjustTemp = ZERO;
                    dateNowOrderTemp = ZERO;
                    dateNowReturnTemp = ZERO;
                    dateEndTemp = ZERO;
                    fpbsEndDate = DateHelper.getLongAgo();//资金池余额日期记录
                    //lastDayOrderDate = DateHelper.getLongAgo();//最后一天要货订单变动金额
                    threeDeference = ZERO;
                    fpbsEndAmt = ZERO;//资金池期末余额
                    lastDayOrderAmt = ZERO;//最后一天要货订单变动金额
                    //这里面就是进行行切换，也就是说 不是一个渠道了，要换下一行,这里面就是个切换的逻辑
                    tempData = new Object[flowFields.length];
                    coll.add(tempData);
                    preChannelNum = tempChannelNum;
                    preOrgName = tempOrgName;
                    preRecCha = tempRecCha;
                }


                Date createDate = (Date) row.get(FPBSConstants.CREATE_DATE);
                //取渠道和组织
                tempData[8] = row.getString(FPBSConstants.CHANNEL_NUM);
                tempData[9] = row.getString(FPBSConstants.FLOW_ORG);
                tempData[11] = row.getString(FPBSConstants.CHANNEL_NAME);
                tempData[12] = row.getString(FPBSConstants.CHANNEL_PAYTYPE);
                tempData[13] = row.getString(FPBSConstants.REC_CHANNEL);
                //接下来的内容就是判断 一个渠道里面的多行数据分别是要货 收款 退货 调整 然后进行数据处理，然后归为一行
                //获取汇总的变动金额
                BigDecimal changeAmt = (BigDecimal) row.get(FPBSConstants.CHANGE_AMOUNT);
                System.out.println("该行变动金额：" + changeAmt.toPlainString());
                Date bizDate = (Date) row.get(FPBSConstants.BIZ_DATE);


                //取更新后余额
                BigDecimal afterUpdateAmt = (BigDecimal) row.get(FPBSConstants.AFTER_AMT);
                //单据类型名称
                String billTypeName = (String) row.get(FPBSConstants.BILL_TYPE_NAME);

                //资金池期末 更新后余额处理
                if ((createDate.compareTo(fpbsEndDate) == 1 || createDate.compareTo(fpbsEndDate) == 0) && checkCreateDateInFtl(createDate, reportQueryParam)) {
                    System.out.println("进资金池期末统计");
                    fpbsEndDate = createDate;
                    fpbsEndAmt = afterUpdateAmt;
                }

                if (bizDate == null) {//没有业务日期的流水信息
                    //要进行三方差异日期判断
                    //if(checkCreateDateInFtl(createDate,reportQueryParam)){
                    //没问题就累加三方差异
                    if ("资金收入单".equals(billTypeName)) {
                        threeDeference = threeDeference.subtract(changeAmt);
                    } else {
                        threeDeference = threeDeference.add(changeAmt);

                    }
                    //}
                    continue;
                }


                //最后一笔要货单数据
                if ("要货订单".equals(billTypeName) && checkBizDateBetweenFtl(bizDate, reportQueryParam)) {
                    System.out.println("进最后一天要货金额统计");
                    //bizDate还得处于日期过滤条件之间
                    //lastDayOrderDate = createDate;
                    lastDayOrderAmt = lastDayOrderAmt.add(changeAmt);
                }
                //先根据业务日期，判断是属于期初 还是本期
                Boolean checkRes = checkBizDate(bizDate, reportQueryParam);
                if (checkRes == null) continue;
                if (checkRes) {
                    System.out.println("期初");
                    //期初
                    //判断一下是加还是减
                    dateFirstTemp = checkBillTypeToDateFirst(billTypeName, changeAmt, dateFirstTemp);
                } else {
                    System.out.println("本期");
                    //本期
                    switch (billTypeName) {
                        case "要货订单"://ocbsoc_saleorder
                            dateNowOrderTemp = dateNowOrderTemp.subtract(changeAmt);
                            break;
                        case "资金收入单"://occba_moneyincome
                        case "渠道资金收入单"://occba_moneyincome_s
                            dateNowGetTemp = dateNowGetTemp.add(changeAmt);
                            break;
                        case "退货申请单"://ocbsoc_returnorder
                            dateNowReturnTemp = dateNowReturnTemp.subtract(changeAmt);
                            break;
                        case "资金池调整单"://occba_balanceadjust
                        case "客户资金池调整单"://occba_cusbalancadjust_b2b
                            dateNowAdjustTemp = dateNowAdjustTemp.add(changeAmt);
                            break;
                        default:
                            break;
                    }

                }


                System.out.println("行结束\n-----------");
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }

        //赋值最后一行
        dateFirstTemp = dateFirstTemp.subtract(threeDeference);
        //查封存期初，获取期初值直接加上来
//        String mapKey = preOrgName + "-" + preChannelNum + "-" + preRecCha;
//        BigDecimal saveDF = saveDFData.get(mapKey);
//        if (saveDF == null) {
//            saveDF = ZERO;
//        }
//        dateFirstTemp = dateFirstTemp.add(saveDF);
        tempData[0] = dateFirstTemp;//todo...这一列已经处理
        tempData[1] = dateNowGetTemp;//todo...这一列已处理
        tempData[2] = dateNowAdjustTemp;//todo...这一列已处理
        tempData[3] = dateNowOrderTemp;//todo...这一列已处理
        tempData[4] = dateNowReturnTemp;//todo...这一列已处理
        tempData[5] = dateEndTemp.add(dateFirstTemp).add(dateNowGetTemp).add(dateNowAdjustTemp).add(dateNowOrderTemp).add(dateNowReturnTemp);//todo...这一列已处理
        //tempData[5] = dateEndTemp.add(dateFirstTemp).add(dateNowGetTemp).add(dateNowAdjustTemp).add(dateNowOrderTemp).add(dateNowReturnTemp);
        tempData[6] = fpbsEndAmt;//todo... 这一列已经处理
        tempData[7] = lastDayOrderAmt;
        tempData[10] = threeDeference;

        return createDataSet;
    }

    private Boolean checkBizDateBetweenFtl(Date bizDate, ReportQueryParam reportQueryParam) throws ParseException {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        //开始日期
        FilterItemInfo endDateItem = filterInfo.getFilterItem("enddate");
        Date endDateFtl = (Date) endDateItem.getValue();
        //获取结束日期当月最后一天
        Date monthLastDay = DateHelper.getMonthLastDay(endDateFtl);
        //开始
        Date beginDate = DateHelper.getdayFirst(monthLastDay);
        //结束
        Date endDate = DateHelper.getDayLast(monthLastDay);

        if ((beginDate.compareTo(bizDate) == -1 && endDate.compareTo(bizDate) == 1) || beginDate.compareTo(bizDate) == 0 || endDate.compareTo(bizDate) == 0) {
            return true;
        } else {
            return false;
        }
    }

    private Boolean checkCreateDateInFtl(Date create, ReportQueryParam reportQueryParam) {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        //开始日期
        FilterItemInfo endDateItem = filterInfo.getFilterItem("enddate");
        Date endDateFtl = (Date) endDateItem.getValue();
//        FilterItemInfo beginDateItem = filterInfo.getFilterItem("begindate");
//        Date beginDateFtl = (Date) beginDateItem.getValue();
        //开始
        //Date beginDate = DateHelper.getdayFirst(beginDateFtl);
        //结束
        Date endDate = DateHelper.getDayLast(endDateFtl);
//        if ((beginDate.compareTo(create) == -1 && endDate.compareTo(create) == 1) || beginDate.compareTo(create) == 0 || endDate.compareTo(create) == 0) {
//            return true;
//        } else {
//            return false;
//        }
        if (endDate.compareTo(create) == 1 || endDate.compareTo(create) == 0) {
            return true;
        } else {
            return false;
        }

    }


    private Boolean checkBizDateBetweenFtl(Date bizDate, ReportQueryParam reportQueryParam, int flag) {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        //开始日期
        FilterItemInfo endDateItem = filterInfo.getFilterItem("enddate");
        Date endDateFtl = (Date) endDateItem.getValue();
        FilterItemInfo beginDateItem = filterInfo.getFilterItem("begindate");
        Date beginDateFtl = (Date) beginDateItem.getValue();
        //获取结束日期当月最后一天
        //开始
        Date beginDate = DateHelper.getdayFirst(beginDateFtl);
        //结束
        Date endDate = DateHelper.getDayLast(endDateFtl);

        if ((beginDate.compareTo(bizDate) == -1 && endDate.compareTo(bizDate) == 1) || beginDate.compareTo(bizDate) == 0 || endDate.compareTo(bizDate) == 0) {
            return true;
        } else {
            return false;
        }
    }

    private Boolean checkBizDateEndFtl(Date bizDate, ReportQueryParam reportQueryParam) {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        FilterItemInfo endDateItem = filterInfo.getFilterItem("enddate");
        Date endDateFtl = (Date) endDateItem.getValue();
        //结束
        Date endDate = DateHelper.getDayLast(endDateFtl);
        if (endDate.compareTo(bizDate) == 1 || endDate.compareTo(bizDate) == 0) {
            return true;
        } else {
            return false;
        }


    }


    private Boolean checkBizDate(Date bizDate, ReportQueryParam reportQueryParam) {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        //开始日期
        FilterItemInfo beginDateItem = filterInfo.getFilterItem("begindate");
        Date beginDate = (Date) beginDateItem.getValue();
        beginDate = DateHelper.getdayFirst(beginDate);

        //结束日期
        FilterItemInfo endDateItem = filterInfo.getFilterItem("enddate");
        Date endDate = (Date) endDateItem.getValue();
        endDate = DateHelper.getDayLast(endDate);

        //属于本期的部分
        if ((beginDate.compareTo(bizDate) == -1 && endDate.compareTo(bizDate) == 1) || beginDate.compareTo(bizDate) == 0 || endDate.compareTo(bizDate) == 0) {
            return false;
        } else if (beginDate.compareTo(bizDate) == 1) {
            //属于期初的部分
            return true;
        } else {
            return null;
        }
    }


    public static BigDecimal checkBillTypeToDateFirst(String billType, BigDecimal changeAmt, BigDecimal dateFirstTemp) {
        switch (billType) {
            case "要货订单":
                dateFirstTemp = dateFirstTemp.subtract(changeAmt);
                break;
            case "资金收入单":
            case "渠道资金收入单":
                dateFirstTemp = dateFirstTemp.add(changeAmt);
                break;
            case "资金池调整单":
            case "客户资金池调整单":
                dateFirstTemp = dateFirstTemp.add(changeAmt);
                break;
            case "退货申请单":
                dateFirstTemp = dateFirstTemp.subtract(changeAmt);
                break;
            default:
                break;
        }
        return dateFirstTemp;
    }


    public static List<List<String>> splitListIntoSublists(List<String> list) {
        List<List<String>> result = new ArrayList<>();

        // 计算需要分成多少个子列表
        int totalElements = list.size();
        int sublistSize = 1000;
        int numberOfSublists = (totalElements + sublistSize - 1) / sublistSize; // 向上取整

        for (int i = 0; i < numberOfSublists; i++) {
            int start = i * sublistSize;
            int end = Math.min(start + sublistSize, totalElements);
            List<String> sublist = list.subList(start, end);
            result.add(new ArrayList<>(sublist)); // 创建一个新列表以避免原始列表的修改影响子列表
        }

        return result;
    }


    public static List<String> getPageFromList(List<List<String>> list, ReportQueryParam reportQueryParam) {
        FilterInfo filterInfo = reportQueryParam.getFilter();
        //客户
        FilterItemInfo pageFilterItem = filterInfo.getFilterItem("bazk_pagenum");
        Integer pageNum = (Integer) pageFilterItem.getValue();
        pageNum = pageNum - 1;

        if (list == null || list.isEmpty()) {
            // 如果列表为空，直接返回空列表
            return Collections.emptyList();
        }

        int size = list.size();
        if (pageNum < 0 || pageNum >= size) {
            // 如果页码超出范围，返回最后一个子列表
            return list.get(size - 1);
        }

        // 返回对应页码的子列表
        return list.get(pageNum);
    }



    @Override
    public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
        //余额
        QFilter oraFilter = getORAFilter(reportQueryParam);
        String selectPart = getORASelect();
        DataSet oraDs = QueryServiceHelper.queryDataSet(algoKey,
                FPBSConstants.ORA_BD,
                selectPart,
                oraFilter.toArray(),
                null).distinct();


        System.out.println("余额查询结果：");
        //oraDs.print(true);
        List<String> chaNumsAll = new ArrayList<>();
        //取渠道编码集合
        for (Row row : oraDs.copy()) {
            String channelNum = (String) row.get(FPBSConstants.CHANNEL_NUM);
            //System.out.println("渠道列表："+channelNum);
            chaNumsAll.add(channelNum);
        }

        List<List<String>> a = splitListIntoSublists(chaNumsAll);
        System.out.println("总共分的页数: " + a.size());
        List<String> chaNums = getPageFromList(a, reportQueryParam);




        //根据起始日期查封存期初
        getSaveDFData(reportQueryParam);
        //查流水
        QFilter qcFilter = getQCFilter(reportQueryParam, chaNums);
        DataSet qcDs = QueryServiceHelper.queryDataSet(algoKey,
                        "occba_flowrecord",
                        "changeamount as " + FPBSConstants.CHANGE_AMOUNT +
                                ",billentity.name as " + FPBSConstants.BILL_TYPE_NAME +
                                ",org.name as " + FPBSConstants.FLOW_ORG +
                                ",sourcebillno as sourceBillno" +
                                ",receivechannel.name as " + FPBSConstants.REC_CHANNEL +
                                ",bazk_bizdate as " + FPBSConstants.BIZ_DATE +
                                ",channel.number as " + FPBSConstants.CHANNEL_NUM +
                                ",channel.name as " + FPBSConstants.CHANNEL_NAME +
                                ",channel.paytype as " + FPBSConstants.CHANNEL_PAYTYPE +
                                ",afteramount as " + FPBSConstants.AFTER_AMT +
                                ",createtime as " + FPBSConstants.CREATE_DATE +
                                ",id as " + FPBSConstants.BILL_ID
                        , qcFilter.toArray(), null)
//                .groupBy(new String[]{
//                        FPBSConstants.BILL_TYPE_NAME,
//                        FPBSConstants.CHANNEL_NUM,
//                        FPBSConstants.BIZ_DATE,
//                        FPBSConstants.FLOW_ORG})
//                .sum(FPBSConstants.CHANGE_AMOUNT)
//                .finish()
                .orderBy(new String[]{FPBSConstants.CHANNEL_NUM,
                        FPBSConstants.FLOW_ORG,
                        FPBSConstants.BILL_ID,
                        FPBSConstants.CREATE_DATE});
        //System.out.println("流水结果：");
        //qcDs.print(true);

        DataSet createQCDs = createDs(qcDs, reportQueryParam);
        //System.out.println("创造结果");
        //createQCDs.print(true);
        // 创建一个新的DataSet用于存储新的一行记录



        String[] qcSelectFields = ArrayListHelper.merge(commonFields, flowFields);
        //连接
        DataSet resDs = oraDs.join(createQCDs)
                .on(FPBSConstants.CHANNEL_NUM, FPBSConstants.CHANNEL_NUM_DATE_FIRST)
                .on(FPBSConstants.ORA_ORG, FPBSConstants.FLOW_ORG)
                .on(FPBSConstants.REC_CHANNEL, FPBSConstants.REC_CHANNEL)
                .select(qcSelectFields)
                .finish();

        DataSet pages = createPageDs(a.size(),qcSelectFields);

        DataSet lastDs = resDs.union(pages);



        return lastDs;
    }



    private DataSet createPageDs(Integer pageTotalNum,String[] qcSelectFields){
        Collection<Object[]> coll = new ArrayList<>();//创建显示行字段
        //下面初始创建一个空的报表数据行
        DataType[] qcDataType = ArrayListHelper.merge(commonDataTypes, flowDataTypes);
        RowMeta createRowMeta = RowMetaFactory.createRowMeta(qcSelectFields, qcDataType);
        CollectionInput collectionInput = new CollectionInput(createRowMeta, coll);
        DataSet createDataSet = Algo.create(this.getClass().getName()).createDataSet(collectionInput);

        Object[] tempData = new Object[qcSelectFields.length];
        coll.add(tempData);

        tempData[0] = pageTotalNum.toString();
        tempData[1] = "总页数";

        return createDataSet;
    }

    private void getSaveDFData(ReportQueryParam reportQueryParam) {
        saveDFData = new HashMap<>();
        FilterInfo filterInfo = reportQueryParam.getFilter();
        FilterItemInfo beginDateItem = filterInfo.getFilterItem("begindate");
        Date beginDateFtl = (Date) beginDateItem.getValue();
        //获得开始日期前三个月的年月信息
        Date threeAgo = DateHelper.getDateThreeMonAgoFromDate(beginDateFtl);
        QFilter qFilter = new QFilter("bazk_savedate", QCP.equals, threeAgo);
        DataSet ds = QueryServiceHelper.queryDataSet(algoKey, "bazk_initialpoolbs",
                "bazk_org.name as orgName" +
                        ",bazk_receivechannel.name as recechaName" +
                        ",bazk_channel.number as chaNum" +
                        ",bazk_datefirst as saveVal"
                , qFilter.toArray(), null);
        Iterator iterator = ds.iterator();
        while (iterator.hasNext()) {
            Row row = (Row) iterator.next();
            String orgName = (String) row.get("orgName");
            String chaNum = (String) row.get("chaNum");
            String recechaName = (String) row.get("recechaName");
            BigDecimal saveVal = (BigDecimal) row.get("saveVal");
            String key = orgName + "-" + chaNum + "-" + recechaName;
            saveDFData.put(key, saveVal);
        }

    }

    @Override
    public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {

        ReportColumn oraId = ReportHelper.createReportColumn("id", "50",
                FPBSConstants.ORA_ID, ReportColumn.TYPE_TEXT, 0, true);
        columns.add(oraId);

        ReportColumn oraNumber = ReportHelper.createReportColumn("资金池编码", "50",
                FPBSConstants.ORA_NUMBER_SQL, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(oraNumber);

        ReportColumn oraOrg = ReportHelper.createReportColumn("结算组织", "50",
                FPBSConstants.ORA_ORG, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(oraOrg);

        ReportColumn oraCusNumber = ReportHelper.createReportColumn("客户编码", "50",
                FPBSConstants.ORA_CUS_NUMBER, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(oraCusNumber);

        ReportColumn oraCusName = ReportHelper.createReportColumn("客户名称", "50",
                FPBSConstants.ORA_CUS_NAME, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(oraCusName);

        ReportColumn oraCusPayType = ReportHelper.createReportColumn("客户支付方式", "50",
                FPBSConstants.ORA_CUS_PAYTYPE, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(oraCusPayType);

        ReportColumn chaNum = ReportHelper.createReportColumn("渠道编码", "50",
                FPBSConstants.CHANNEL_NUM_DATE_FIRST, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(chaNum);
        //FPBSConstants.CHANNEL_NUM_DATE_FIRST

        ReportColumn chaName = ReportHelper.createReportColumn("渠道名称", "50",
                FPBSConstants.CHANNEL_NAME, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(chaName);

        ReportColumn recChaName = ReportHelper.createReportColumn("收款渠道名称", "50",
                FPBSConstants.REC_CHANNEL, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(recChaName);

        ReportColumn chaPayType = ReportHelper.createReportColumn("渠道支付方式", "50",
                FPBSConstants.CHANNEL_PAYTYPE, ReportColumn.TYPE_TEXT, 0, false);
        columns.add(chaPayType);


        ReportColumn dateFirst = ReportHelper.createReportColumn("期初", "50",
                FPBSConstants.DATE_FIRST, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(dateFirst);
        //本期收款
        ReportColumn dateGet = ReportHelper.createReportColumn("本期收款", "50",
                FPBSConstants.DATE_GET, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(dateGet);

        //本期订货
        ReportColumn dateOrder = ReportHelper.createReportColumn("本期订货", "50",
                FPBSConstants.DATE_ORDER, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(dateOrder);

        //本期退货
        ReportColumn dateReturn = ReportHelper.createReportColumn("本期退货", "50",
                FPBSConstants.DATE_RETURN, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(dateReturn);

        //本期调整
        ReportColumn dateAdjust = ReportHelper.createReportColumn("本期调整", "50",
                FPBSConstants.DATE_ADJUST, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(dateAdjust);
//
        //统计期末余额
        ReportColumn dateEnd = ReportHelper.createReportColumn("统计期末余额", "50",
                FPBSConstants.DATE_END, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(dateEnd);

        //资金池期末余额
        ReportColumn fpbsEndAmt = ReportHelper.createReportColumn("资金池期末余额", "50",
                FPBSConstants.FPBS_END_AMT, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(fpbsEndAmt);

        //资金池期末余额
        ReportColumn lastDayOrderAmt = ReportHelper.createReportColumn("本月最后一天要货金额", "50",
                FPBSConstants.LAST_DAY_AMT, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(lastDayOrderAmt);

        //三方差异
        ReportColumn tripartiteDifferences = ReportHelper.createReportColumn("三方差异", "50",
                FPBSConstants.TRIPARTITE_DIFFERENCES, ReportColumn.TYPE_DECIMAL, 2, false);
        columns.add(tripartiteDifferences);


        return super.getColumns(columns);
    }

}
